/*
 * HamamatsuS12573100C.cc
 *
 * @date Apr 11, 2016
 * @author Tim Niggemann, III Phys. Inst. A, RWTH Aachen University
 * @copyright GNU General Public License v3.0
 */

#include "model/impl/HamamatsuS12573100C.hh"

#include <boost/format.hpp>

#include "MaterialFactory.hh"
#include "VectorUtil.hh"
#include "InterpolationUtil.hh"
#include "model/impl/G4SipmRandomGainMapModel.hh"

HamamatsuS12573100C::HamamatsuS12573100C() : G4SipmModel(new G4SipmRandomGainMapModel, new VoltageTraceModel)
{
	setTemperature(25 * CLHEP::kelvin + CLHEP::STP_Temperature);
	setBiasVoltage(getBreakdownVoltage() + 1.4 * CLHEP::volt);
	getGainMapModel()->refresh(this);
	// PDE from the Hamamatsu 13360-6050pe (same resin, metal sheet quenching resistor) scaled to peak at 35 %.
	static const double x[] = {312.43521216058548, 319.96168505372179, 320.78402733330984, 321.6512874685057,
							   322.57728633795779, 323.42035993551872, 324.16668738253981, 324.85427609530461, 325.50385739178597,
							   326.12579693097024, 326.72354993251957, 327.30748205542034, 327.87759329967258, 328.43388366527631,
							   328.97980837189357, 329.51536741952452, 330.04401602783111, 330.56575419681349, 331.08058192647155,
							   331.59195443646752, 332.09641650713922, 332.59742335814872, 333.09151976983401, 333.58216096185714,
							   334.06934693421817, 334.55653290657915, 335.03680843961592, 335.51362875299048, 335.9904490663651,
							   336.46381416007756, 336.93372403412792, 337.40363390817822, 337.87008856256648, 338.33308799729252,
							   338.79608743201857, 339.25908686674461, 339.71863108180855, 340.1747200772104, 340.63426429227422,
							   341.09035328767607, 341.54644228307791, 341.99907605881754, 342.45516505421932, 342.90779882995901,
							   343.36388782536073, 343.81652160110042, 344.27261059650226, 344.72869959190399, 345.18824380696799,
							   345.65124324169403, 346.15570531236568, 346.70854045830725, 347.31665911884295, 347.96969563498646,
							   348.66419478707553, 349.39670135544816, 350.16721534010424, 350.9722815213816, 351.80844467961822,
							   352.67224959515192, 353.56369626798272, 354.47932947844845, 355.42260444621121, 356.3831555122847,
							   357.36789311599307, 358.36990681801217, 359.389196618342, 360.42576251698245, 361.47614929427141,
							   362.53690173054679, 363.60801982580858, 364.68604836039464, 365.77098733430495, 366.8524710885531,
							   367.92704440347711, 368.98088640042818, 369.98981054177153, 370.97800336514211, 371.96619618851264,
							   372.95784423154532, 373.95294749424016, 374.96187163558352, 375.97770621625114, 377.00390645590517,
							   378.04392757420777, 379.09431435149673, 380.16543244675853, 381.25037142066884, 382.35258649288983,
							   383.4755328830837, 384.62266581091239, 385.79744049603823, 387.00331215812332, 388.2437360168297,
							   389.52907773114384, 390.86624774039001, 392.27252214287887, 393.76172181725894, 395.37876461913805,
							   397.18584450243458, 399.33844635194453, 401.64653308625054, 403.80950059474696, 405.88608761169002,
							   407.91775677302525, 409.94597071469838, 411.99146075468218, 414.08532386993585, 416.25174659809443,
							   418.51491547679268, 420.89556182400361, 423.41441695769981, 426.08875697619214, 428.93585797779122,
							   431.85551859229508, 434.76481354781265, 437.66719806400585, 440.57303779986125, 443.50306407335154,
							   446.47455298278749, 449.51514628546613, 452.66976183699512, 455.98331749298245, 459.42126105680654,
							   462.82810764367144, 466.18312593560438, 469.49668159159165, 472.77914027061973, 476.03050197268857,
							   479.26113235678457, 482.46412098358354, 485.64637829240968, 488.80444906360088, 491.93487807749506,
							   495.02384445544351, 498.06098253846, 500.95300139566689, 503.59969965686213, 506.12201001022055,
							   508.56830553101202, 510.9627727568714, 513.31923256644734, 515.63768495973977, 517.92849559573506,
							   520.19511969409564, 522.43755725482106, 524.65580827791155, 526.84987276336722, 529.01975071118795,
							   531.16198690171132, 533.27658133493787, 535.35662357154308, 537.38483751321621, 539.38540969759231,
							   541.41707885892754, 543.46256889891129, 545.51842459788145, 547.57773551651383, 549.6405016548083,
							   551.7101782324271, 553.77639959038368, 555.84953138766468, 557.91920796528325, 559.99233976256414,
							   562.06547155984504, 564.13860335712593, 566.20827993474472, 568.28141173202562, 570.35108830964441,
							   572.42076488726309, 574.48698624521967, 576.55320760317636, 578.61942896113283, 580.67873987976532,
							   582.73805079839758, 584.79045127770564, 586.83594131768939, 588.87452091834894, 590.90273486002206,
							   592.91367270338458, 594.91078966809846, 597.00119756369008, 599.18489639015922, 601.43078917054686,
							   603.72159980654214, 606.03659698017259, 608.35159415380281, 610.66313610777104, 612.94703630444212,
							   615.19638430449197, 617.39735922927184, 619.532684980471, 621.5989063384277, 623.57874720483096,
							   625.4652971403566, 627.24819048601807, 628.92051680249142, 630.47882087011408, 632.18224416354656,
							   634.08952541704502, 636.12810501770457, 638.26343076890385, 640.47131613300803, 642.73448501170628,
							   645.0425717460123, 647.38866589660188, 649.76585702415059, 652.16723468933446, 654.59279889215304,
							   657.03909441294445, 659.49921081238426, 661.97314809047293, 664.45745102754779, 666.95211962360918,
							   669.45024343933255, 671.94836725505604, 674.44649107077953, 676.9307940078545, 679.39782084661874,
							   681.92704163930148, 684.49772506792965, 687.09259503419298, 689.70128587910472, 692.32725282232707,
							   694.96358542453595, 697.60682846606903, 700.26043716658864, 702.92095630643234, 705.58838588560047,
							   708.2661811237549, 710.94743158157155, 713.6355924787124, 716.33066381517756, 719.02919037130482,
							   721.7380825864185, 724.45043002119439, 727.17314311495659, 729.89931142838088, 732.63239018112949,
							   735.37237937320242, 738.12273422426176, 740.87999951464531, 743.64417524435316, 746.41871663304744,
							   749.20362368072813, 751.99889638739512, 754.80453475304853, 757.62399399735057, 760.45727412030101,
							   763.30437512190019, 766.1722074414721, 769.06422629867882, 771.97697647385849, 774.91391318667308,
							   777.8612155584741, 780.82579402858573, 783.79728293802168, 786.78259272610615, 789.77481295351492,
							   792.77394362024791, 795.78343994596742, 798.7963914913488, 801.81970869571671, 804.84648111974695,
							   807.88016398310128, 810.92075728577993, 813.96826102778277, 817.01921998944783, 820.07363417077499,
							   823.13841401108857, 826.20664907106425, 829.27833935070203, 832.35694006966412, 835.44245122795041,
							   838.53141760589904, 841.62383920350965, 844.72662646010667, 847.83286893636591, 850.94602185194947,
							   854.06608520685711, 857.18960378142697, 860.32348801498324, 863.46428268786383, 866.60853258040652,
							   869.76314813193551, 872.92812934245092, 876.10002099229087, 879.28227830111689, 882.47490126892956,
							   885.67788989572841, 888.89469940117579, 892.1253297852719, 895.37323626767852, 1009.241589634405};
	static const double y[] = {0, 2.6219259622907436, 2.9083975411238367, 3.1936890104663829, 3.4778003703183429,
							   3.7636818944061625, 4.0516286101024193, 4.3404604079166251, 4.6301772878487322, 4.9201891951534753,
							   5.2104961298309229, 5.5010980918809302, 5.791995081303642, 6.0828920707262855, 6.3740840875216245,
							   6.6652761043169635, 6.9564681211122439, 7.247955165280219, 7.5397372368208213, 7.8312242809887973,
							   8.1227113251567147, 8.414493396697317, 8.7062754682379282, 8.9980575397785305, 9.2901346386917698,
							   9.5819167102323828, 9.873993809145583, 10.166070908058822, 10.457852979599433, 10.749930078512673,
							   11.042007177425912, 11.334379303711779, 11.626456402625017, 11.918533501538267, 12.210610600451506,
							   12.502982726737383, 12.795059825650611, 13.087431951936487, 13.379509050849736, 13.671881177135612,
							   13.963958276048841, 14.256330402334717, 14.548702528620593, 14.840779627533822, 15.133151753819698,
							   15.425523880105574, 15.717600979018814, 16.009973105304681, 16.30205020421792, 16.594422330503832,
							   16.885909374671769, 17.17710139146708, 17.467113298771864, 17.756830178703968, 18.045661976518183,
							   18.333608692214462, 18.620965353165452, 18.907731959371166, 19.193908510831619, 19.479199980174137,
							   19.764196422144028, 20.048307781996016, 20.332124114475349, 20.615350392209372, 20.897986615198157,
							   21.180032783441622, 21.461783924312488, 21.742945010438053, 22.02381106919098, 22.304382100571278,
							   22.584658104578942, 22.864639081213941, 23.144620057848975, 23.424601034483974, 23.704877038491638,
							   23.985743097244576, 24.267494238115404, 24.55013046110416, 24.832766684092952, 25.115107879709075,
							   25.397449075325213, 25.67920021619604, 25.961246384439534, 26.242702497937763, 26.523863584063321,
							   26.804729642816259, 27.085005646823923, 27.364986623458918, 27.644377545348654, 27.922883385120457,
							   28.201094197519627, 28.478419927800896, 28.754565548591604, 29.029826087264379, 29.303316461701328,
							   29.575331699275047, 29.844691690495033, 30.110511353243361, 30.371020523284134, 30.622088817400467,
							   30.852210168059408, 31.071415505930638, 31.301241829216906, 31.53667367258333, 31.775055789676152,
							   32.013732934141615, 32.25122996911653, 32.485481702992395, 32.71501299890604, 32.937758665248964,
							   33.151653510412707, 33.353157205925569, 33.539319478061167, 33.706009943602581, 33.863554560592142,
							   34.022574314444896, 34.182184123042923, 34.340908849523053, 34.496978329649416, 34.647442289695626,
							   34.786695209581531, 34.906476322873239, 34.988788959839695, 35.0, 34.953680702495568, 34.884054242552622,
							   34.801151550840892, 34.709398037949967, 34.610563868115676, 34.505829150828589, 34.396373995579303,
							   34.281903374995146, 34.162417289076068, 34.037915737822168, 33.906628556997518, 33.766195527621051,
							   33.605405609532461, 33.416293063670437, 33.215084395530198, 33.00709009781928, 32.794670389518735,
							   32.578710352746533, 32.3603900969932, 32.140004649631372, 31.917258983288452, 31.693038180082333,
							   31.467047212640384, 31.239581108335233, 31.010344839794229, 30.779043379644762, 30.545971755259465,
							   30.310539911893034, 30.072157794800212, 29.831710486098896, 29.593328369006066, 29.35583133403118,
							   29.118924353801557, 28.882312400944567, 28.64570044808757, 28.409678549975848, 28.173656651864153,
							   27.937634753752455, 27.701907883013362, 27.465885984901675, 27.23015911416261, 26.99443224342355,
							   26.758410345311823, 26.522683474572759, 26.286661576461071, 26.050639678349341, 25.814617780237644,
							   25.578300854753284, 25.341983929268959, 25.105371976411966, 24.868464996182343, 24.63155801595272,
							   24.394060980977791, 24.155973891257645, 23.917591774164784, 23.677734520208769, 23.437287211507481,
							   23.202740450258947, 22.974094236463241, 22.750463488002421, 22.529783013267959, 22.310872702769366,
							   22.092257419643399, 21.873052081772137, 21.652076579665049, 21.428445831204229, 21.200979726899043,
							   20.969678266749572, 20.733361341265244, 20.491733923073369, 20.244796012173996, 19.992252581194474,
							   19.734398657507416, 19.471234241112889, 19.21485545428904, 18.969097652880244, 18.731305590532674,
							   18.499709103010577, 18.272833053450693, 18.050087387107773, 17.830882049236514, 17.614626985091679,
							   17.400732139927928, 17.188902486372683, 16.979138024425897, 16.770848699342324, 16.564034511121932,
							   16.358400432392106, 16.153651435780212, 15.949787521286215, 15.746218634164887, 15.542944774416155,
							   15.339080859922159, 15.134331863310265, 14.928107729835176, 14.727489116440205, 14.530410831516932,
							   14.335987792947408, 14.14303989124109, 13.951567126397963, 13.760979443672776, 13.571276843065489,
							   13.38275435194876, 13.194821915577332, 13.007774561323796, 12.821317261815523, 12.635745044425228,
							   12.45046785440752, 12.266075746507754, 12.082568720725906, 11.899356722316666, 11.717324833398031,
							   11.535587971852024, 11.354736192423907, 11.174769495113768, 10.995392852548854, 10.816901292101861,
							   10.639294813772805, 10.462868444934317, 10.28732715821373, 10.112670953611071, 9.9394898858716054,
							   9.7677839549953536, 9.5975531609822742, 9.4290925312050451, 9.2624020656636272, 9.0983668464760168,
							   8.9369868736421267, 8.7788522019072612, 8.6236678038988313, 8.4702535701262303, 8.3189045279621254,
							   8.1690306226611842, 8.0206318542233976, 7.8734131952762754, 7.727374645819622, 7.5825162058535733,
							   7.4388378753780424, 7.2963396543931172, 7.1544314881534552, 7.0137034314043314, 6.8738604567731558,
							   6.7349025642598805, 6.59712478123721, 6.459937052959746, 6.3236344068002399, 6.1882168427586253,
							   6.0539793882076154, 5.9203319884018688, 5.7878646980866506, 5.655987462516773, 5.5252903364374131,
							   5.3957733198485913, 5.2671413853777374, 5.1393945330247837, 5.0128277901623477, 4.8877361841631544,
							   4.7635296602818515, 4.6407982732637807, 4.5195420231088734, 4.3997609098171893, 4.2814549333886793,
							   4.1649191211960375, 4.050448500611882, 3.9380430716361547, 3.8282928890142554, 3.7211979527460568,
							   3.6170532902042449, 3.5167439835067982, 0};
	wvl = std::vector<double>(x, x + sizeof(x) / sizeof(x[0]));
	pde = std::vector<double>(y, y + sizeof(y) / sizeof(y[0]));
	// Apply units.
	wvl = VectorUtil::times(wvl, CLHEP::nanometer);
	pde = VectorUtil::times(pde, CLHEP::perCent);
	// Initialize window material.
	windowMaterial = new G4Material(boost::str(boost::format("%s-windowMaterial") % getName()),
									1.0 * CLHEP::g / CLHEP::cm3, MaterialFactory::getInstance()->getEpoxy());
	double energies[] = {1 * CLHEP::eV, 10 * CLHEP::eV};
	double rindex = 1.55;
	double indices[] = {rindex, rindex};
	// Set material properties table.
	G4MaterialPropertiesTable *mpt = new G4MaterialPropertiesTable();
	mpt->AddProperty("RINDEX", energies, indices, 2);
	windowMaterial->SetMaterialPropertiesTable(mpt);
}

HamamatsuS12573100C::~HamamatsuS12573100C()
{
	//
}

std::string HamamatsuS12573100C::getName() const
{
	return "Hamamatsu S12573-100C";
}

double HamamatsuS12573100C::getBreakdownVoltage() const
{
	return 65 * CLHEP::volt;
}

unsigned int HamamatsuS12573100C::getNumberOfCells() const
{
	return 3600;
}

double HamamatsuS12573100C::getCellPitch() const
{
	return 0.1 * CLHEP::mm;
}

double HamamatsuS12573100C::getThermalNoiseRate() const
{
	return 2.89 * CLHEP::megahertz;
}

double HamamatsuS12573100C::getDeadTime() const
{
	return CLHEP::picosecond;
}

double HamamatsuS12573100C::getRecoveryTime() const
{
	return 22.8 * CLHEP::nanosecond;
}

double HamamatsuS12573100C::getCrossTalkProbability() const
{
	return 35.0 * CLHEP::perCent;
}

double HamamatsuS12573100C::getApProbLong() const
{
	return 0.5 * CLHEP::perCent;
}

double HamamatsuS12573100C::getApProbShort() const
{
	return 0.5 * CLHEP::perCent;
}

double HamamatsuS12573100C::getApTauLong() const
{
	return 85.0 * CLHEP::nanosecond;
}

double HamamatsuS12573100C::getApTauShort() const
{
	return 15.0 * CLHEP::nanosecond;
}

double HamamatsuS12573100C::getFillFactor() const
{
	return 78.5 * CLHEP::perCent;
}

double HamamatsuS12573100C::getGainVariation() const
{
	return 10.0 * CLHEP::perCent;
}

double HamamatsuS12573100C::getPhotonDetectionEfficiency(double wavelength) const
{
	return InterpolationUtil::linear(wvl, pde, wavelength);
}

G4Material *HamamatsuS12573100C::getWindowMaterial() const
{
	return windowMaterial;
}

double HamamatsuS12573100C::getWindowThickness() const
{
	return 0.2 * CLHEP::mm;
}

HamamatsuS12573100C::VoltageTraceModel::VoltageTraceModel() : G4SipmVoltageTraceModel()
{
	//
}

double HamamatsuS12573100C::VoltageTraceModel::getAmplitude() const
{
	return 1.0;
}

double HamamatsuS12573100C::VoltageTraceModel::getTauRise() const
{
	return 1.0 * CLHEP::nanosecond;
}

double HamamatsuS12573100C::VoltageTraceModel::getTauFall() const
{
	return 22.8 * CLHEP::nanosecond;
}

double HamamatsuS12573100C::VoltageTraceModel::getV0() const
{
	return 0.0;
}

double HamamatsuS12573100C::VoltageTraceModel::getWhiteNoiseSigma() const
{
	return 0.01;
}

int HamamatsuS12573100C::VoltageTraceModel::getPrecision() const
{
	return 12;
}

double HamamatsuS12573100C::VoltageTraceModel::getTimeBinWidth() const
{
	return 1.0 * CLHEP::nanosecond;
}
